/* Microsoft Reference Implementation for TPM 2.0
 *
 *  The copyright in this software is being made available under the BSD License,
 *  included below. This software may be subject to other third party and
 *  contributor rights, including patent rights, and no such rights are granted
 *  under this license.
 *
 *  Copyright (c) Microsoft Corporation
 *
 *  All rights reserved.
 *
 *  BSD License
 *
 *  Redistribution and use in source and binary forms, with or without modification,
 *  are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice, this list
 *  of conditions and the following disclaimer.
 *
 *  Redistributions in binary form must reproduce the above copyright notice, this
 *  list of conditions and the following disclaimer in the documentation and/or
 *  other materials provided with the distribution.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 *  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 *  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include "Tpm.h"
#include "PCR_SetAuthPolicy_fp.h"

#if CC_PCR_SetAuthPolicy  // Conditional expansion of this file

/*(See part 3 specification)
// Set authPolicy to a group of PCR
*/
//  Return Type: TPM_RC
//      TPM_RC_SIZE                 size of 'authPolicy' is not the size of a digest
//                                  produced by 'policyDigest'
//      TPM_RC_VALUE                PCR referenced by 'pcrNum' is not a member
//                                  of a PCR policy group
/*
为一个PCR组设定一个授权policy。在PC客户端上并不需要这个命令。

This command is used to associate a policy with a PCR or group of PCR. The policy determines theconditions under which a PCR may be extended or reset.
A policy may only be associated with a PCR that has been defined by a platform-specific specification as allowing a policy. If the TPM implementation 
does not allow a policy for pcrNum, the TPM shall return TPM_RC_VALUE.
A platform-specific specification may group PCR so that they share a common policy. In such case, a pcrNum that selects any of the PCR in the group will 
change the policy for all PCR in the group.
The policy setting is persistent and may only be changed by TPM2_PCR_SetAuthPolicy() or by TPM2_ChangePPS().
Before this command is first executed on a TPM or after TPM2_ChangePPS(), the access control on the PCR will be set to the default value defined in the 
platform-specific specification.
NOTE 1 It is expected that the typical default will be with the policy hash set to TPM_ALG_NULL and an Empty Buffer for the authPolicy value. This will 
allow an EmptyAuth to be used as the authorization value.

此命令用于将策略与 PCR 或 PCR 组相关联。 该策略决定了 PCR 可以被扩展或重置的条件。
策略只能与已由特定于平台的规范定义为允许策略的 PCR 相关联。 如果 TPM 实现不允许 pcrNum 策略，则 TPM 应返回 TPM_RC_VALUE。
特定于平台的规范可以对 PCR 进行分组，以便它们共享共同的策略。 在这种情况下，选择组中任何 PCR 的 pcrNum 将更改组中所有 PCR 的策略。
策略设置是持久的，只能由 TPM2_PCR_SetAuthPolicy() 或 TPM2_ChangePPS() 更改。
在 TPM 上首次执行此命令之前或在 TPM2_ChangePPS() 之后，PCR 上的访问控制将设置为平台特定规范中定义的默认值。
注 1 预期典型的默认值是将策略散列设置为 TPM_ALG_NULL 和一个用于 authPolicy 值的空缓冲区。 这将允许将 EmptyAuth 用作授权值。

If the size of the data buffer in authPolicy is not the size of a digest produced by hashAlg, the TPM shall return TPM_RC_SIZE.
NOTE 2 If hashAlg is TPM_ALG_NULL, then the size is required to be zero.
This command requires platformAuth/platformPolicy.
NOTE 3 If the PCR is in multiple policy sets, the policy will be changed in only one set. The set that is changed will be implementation dependent.

如果 authPolicy 中数据缓冲区的大小不是 hashAlg 生成的摘要的大小，TPM 将返回 TPM_RC_SIZE。
注 2 如果 hashAlg 为 TPM_ALG_NULL，则大小必须为零。
此命令需要 platformAuth/platformPolicy。
注 3 如果 PCR 在多个策略集中，则策略将仅在一个集中更改。 更改的集合将取决于实现。

*/
TPM_RC
TPM2_PCR_SetAuthPolicy(
    PCR_SetAuthPolicy_In    *in             // IN: input parameter list
    )
{
    UINT32      groupIndex;

    // The command needs NV update.  Check if NV is available.
    // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
    // this point
    RETURN_IF_NV_IS_NOT_AVAILABLE;

// Input Validation:

    // Check the authPolicy consistent with hash algorithm
    if(in->authPolicy.t.size != CryptHashGetDigestSize(in->hashAlg))
        return TPM_RCS_SIZE + RC_PCR_SetAuthPolicy_authPolicy;

    // If PCR does not belong to a policy group, return TPM_RC_VALUE
    if(!PCRBelongsPolicyGroup(in->pcrNum, &groupIndex))
        return TPM_RCS_VALUE + RC_PCR_SetAuthPolicy_pcrNum;

// Internal Data Update

    // Set PCR policy
    gp.pcrPolicies.hashAlg[groupIndex] = in->hashAlg;
    gp.pcrPolicies.policy[groupIndex] = in->authPolicy;

    // Save new policy to NV
    NV_SYNC_PERSISTENT(pcrPolicies);

    return TPM_RC_SUCCESS;
}

#endif // CC_PCR_SetAuthPolicy